package com.deeper.customview.ui.c8.demo.c08d01;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Scroller;

import com.deeper.customview.R;

public class SliderMenu extends ViewGroup {
    private static final String TAG = "SliderMenu";

    private static final int DO_MOVING = 0x001;//可以滑动
    private static final int NOT_MOVING = 0x002;//不可以滑动
    private int moving = NOT_MOVING;//是否可以滑动，默认不能滑动


    private static final int FLAG_SEPARATOR = 0x1;//标记变量，是否有分割线，占用最后一位
    private static final int FLAG_IS_OPEN = FLAG_SEPARATOR << 1;//标记变量，是否已打开，占用倒数第二位
    private int flags = FLAG_SEPARATOR >> 1;//存储标记变量

    private final int slidingWidth;
    private final float separator;
    private final int touchWidth;
    private final int screenWidth;
    private final Scroller scroller;
    private final Paint paint;
    private int preX;
    private int firstX;


    public SliderMenu(Context context) {
        this(context, null, 0);
    }


    public SliderMenu(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }


    public SliderMenu(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SliderMenu);

        slidingWidth = typedArray.getDimensionPixelSize(R.styleable.SliderMenu_sliding_width,
                (int) TypedValue.applyDimension(
                        TypedValue.COMPLEX_UNIT_DIP, 150,
                        getResources().getDisplayMetrics()));
        separator = typedArray.getDimensionPixelSize(R.styleable.SliderMenu_seperator,
                (int) TypedValue.applyDimension(
                        TypedValue.COMPLEX_UNIT_DIP, 1,
                        getResources().getDisplayMetrics()
                ));
        touchWidth = typedArray.getDimensionPixelSize(R.styleable.SliderMenu_touch_width,
                (int) TypedValue.applyDimension(
                        TypedValue.COMPLEX_UNIT_DIP, 50,
                        getResources().getDisplayMetrics()
                ));
        typedArray.recycle();

        if (separator > 0) {
            flags = flags | FLAG_SEPARATOR;
        }
        screenWidth = getScreenWidth(context);
        setBackgroundColor(Color.alpha(255));

        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.GRAY);
        paint.setStrokeWidth(separator);

        scroller = new Scroller(context);
    }


    /**
     * 子元素不能超过2个
     */
    @Override
    public void addView(View child, int index, LayoutParams params) {
        super.addView(child, index, params);
        if (getChildCount() > 2) {
            throw new ArrayIndexOutOfBoundsException("Children count can't be more than 2.");
        }
    }


    private int getScreenWidth(Context context) {
        WindowManager wm = (WindowManager) context
                .getSystemService(Context.WINDOW_SERVICE);

        Point point = new Point();
        wm.getDefaultDisplay().getSize(point);
        return point.x;
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        measureChildren(widthMeasureSpec, heightMeasureSpec);
        getChildAt(0).getLayoutParams().width = slidingWidth;
        setMeasuredDimension(measureWidth(widthMeasureSpec),
                measureHeight(heightMeasureSpec));
    }


    private int measureWidth(int widthMeasureSpec) {
        int mode = MeasureSpec.getMode(widthMeasureSpec);
        int size = MeasureSpec.getSize(widthMeasureSpec);
        if (mode == MeasureSpec.AT_MOST) {
            throw new IllegalStateException("layout_weight cannot be wrap_content");
        }

        return (int) (screenWidth + slidingWidth + separator);
    }


    private int measureHeight(int heightMeasureSpec) {
        int mode = MeasureSpec.getMode(heightMeasureSpec);
        int size = MeasureSpec.getSize(heightMeasureSpec);
        if (mode == MeasureSpec.AT_MOST) {
            throw new IllegalStateException("layout_height cannot be wrap_content");
        }
        int height = 0;
        if (mode == MeasureSpec.EXACTLY) {
            height = size;
        }
        return height;
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //划分割线
        if ((flags & FLAG_SEPARATOR) == FLAG_SEPARATOR) {
            int left = (int) (slidingWidth + separator / 2);
            canvas.drawLine(left, 0, left, getMeasuredHeight(), paint);
        }
    }


    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int n = getChildCount();
        View child = null;
        int left = 0;
        int top = 0;
        int right = 0;
        int bottom = 0;
        for (int i = 0; i < n; i++) {
            child = getChildAt(i);
            if (i == 0) { //第一个
                left = -child.getMeasuredWidth();
                top = 0;
                right = 0;
                bottom = b;
            } else {//第二个
                left = 0;
                top = 0;
                right = child.getMeasuredWidth();
                bottom = b;
            }
            child.layout(left, top, right, bottom);
        }
    }


    /**
     * 判断是否可以滑动
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if ((flags & FLAG_IS_OPEN) == FLAG_IS_OPEN) {
                    moving = DO_MOVING;
                } else {
                    if (ev.getX() > touchWidth) {
                        moving = NOT_MOVING;
                    } else {
                        moving = DO_MOVING;
                    }
                }
                break;
            case MotionEvent.ACTION_MOVE:
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                moving = NOT_MOVING;
                break;
        }
        return super.onInterceptTouchEvent(ev);
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (moving == NOT_MOVING) {
            return false;
        }
        int x = (int) event.getX();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                preX = x;
                firstX = x;
                break;
            case MotionEvent.ACTION_MOVE:
                int dx = x - preX;
                this.scrollBy(-dx, 0);
                preX = x;
                break;
            case MotionEvent.ACTION_UP:
                dx = x - firstX;
                int remain = slidingWidth - Math.abs(dx);
                //dx 右为正，左为负
                boolean isOpen = (flags & FLAG_IS_OPEN) == FLAG_IS_OPEN;
                if (dx > 0 && !isOpen) {
                    scroller.startScroll(getScrollX(), 0, -remain, 0);
                    flags = flags | FLAG_IS_OPEN;
                } else if (dx < 0 && isOpen) {
                    scroller.startScroll(getScrollX(), 0, remain, 0);
                    flags = flags & ~FLAG_IS_OPEN;
                } else {
                    //校正
                    scroller.startScroll(getScrollX(), 0, dx, 0);
                }
                invalidate();
                break;
        }
        return moving == DO_MOVING;
    }


    @Override
    public void computeScroll() {
        if (scroller.computeScrollOffset()) {
            this.scrollTo(scroller.getCurrX(), 0);
            postInvalidate();
        }
    }


    public void open() {
        boolean isOpen = (flags & FLAG_IS_OPEN) == FLAG_IS_OPEN;
        if (!isOpen) {
            scroller.startScroll(slidingWidth, 0, -slidingWidth, 0);
            invalidate();
            flags = flags | FLAG_IS_OPEN;
        }
    }


    public void close() {
        boolean isOpen = (flags & FLAG_IS_OPEN) == FLAG_IS_OPEN;
        if (isOpen) {
            scroller.startScroll(0, 0, slidingWidth, 0);
            invalidate();
            flags = flags & ~FLAG_IS_OPEN;
        }
    }


    public void toggle() {
        boolean isOpen = (flags & FLAG_IS_OPEN) == FLAG_IS_OPEN;
        if (isOpen) {
            close();
        } else {
            open();
        }
    }
}
